<template>
  <transition name="fade">
    <div class="zh-audio-player">
      <img
        :class="
          isPlay
            ? 'audio-viewer-index'
            : 'audio-viewer-index audio-viewer-index-pause'
        "
        src="../../../public/images/audio-index.png"
        alt="音频指针"
      />
      <div class="audio-viewer-wrapper">
        <div class="audio-viewer-image">
          <div>
            <div
              :class="
                isPlay
                  ? 'audio-viewer-image-status audio-viewer-image-play'
                  : 'audio-viewer-image-status'
              "
            ></div>
          </div>
        </div>
        <div class="audio-viewer-actions">
          <template v-if="isSupport">
            <div class="audio-action-status">
              <i
                v-if="isPlay"
                class="el-icon-video-pause"
                @click="audioPause"
              ></i>
              <i v-else class="el-icon-video-play" @click="audioPlay"></i>
              <el-slider
                class="audio-volume-sound"
                v-if="volume"
                v-model="sound"
                :show-tooltip="false"
                vertical
                height="60px"
                :min="0"
                :max="100"
              ></el-slider>
            </div>
            <div class="audio-action-info">
              <p class="audio-title" :title="audioContent.name">
                {{ audioContent.name }}
              </p>
              <div class="audio-volume">
                <el-slider
                  v-model="musicInfo.currentTime"
                  @input="inputTime"
                  @change="changeTime"
                  :show-tooltip="false"
                  :disabled="isChange"
                  :min="0"
                  :max="musicInfo.duration"
                ></el-slider>
                <div class="audio-time">
                  <span>{{ formatTime(musicInfo.currentTime) }}</span>
                  <span>{{ formatTime(musicInfo.duration) }}</span>
                </div>
              </div>
            </div>
          </template>
          <template v-else>
            <div class="no-support">
              音频文件,仅支持：MP3、Wav、Ogg格式的播放
            </div>
          </template>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
export default {
  name: "audioPlayer",
  props: {
    audioContent: {
      type: Object,
      default: () => {}
    },
    onClose: {
      type: Function,
      default: () => {}
    },
    volume: {
      type: Boolean,
      default: () => false
    },
    autoplay: {
      type: Boolean,
      default: () => false
    },
    loop: {
      type: Boolean,
      default: () => false
    },
    muted: {
      type: Boolean,
      default: () => false
    }
  },
  data() {
    return {
      showAudio: true,
      isPlay: false, // 是否播放状态
      audioNode: null, // audio 对象
      isChange: true, // 是否禁用进度条
      sound: 50, // 默认音量
      isCanPlay: false, // 暂停状态不可以自动播放
      isNoInput: false, // 进度条拖拽时, input 事件不出来
      musicInfo: {
        duration: 0,
        currentTime: 0
      },
      isSupport: true
    };
  },
  mounted() {
    let urlSplit = this.audioContent.url.split(".");
    let postfix = urlSplit[urlSplit.length - 1];
    if (!["ogg", "mp3", "wav", "MP3"].includes(postfix)) {
      this.isSupport = false;
      this.$message.warning("不支持" + postfix + "文件格式的播放");
      return;
    }

    this.audioNode = new Audio();
    this.audioNode.src = this.audioContent.url;
    this.muted && (this.sound = 0);

    this.audioNode.addEventListener("loadedmetadata", () => {
      // 语音元数据主要是语音的长度之类的数据
      this.isChange = false;
      this.musicInfo.duration = this.audioNode.duration;
      this.autoplay && this.audioPlay();
      this.loop && (this.audioNode.loop = true);
    });
    this.audioNode.addEventListener("timeupdate", () => {
      // 当timeupdate事件大概每秒一次，用来更新音频流的当前播放时间
      this.musicInfo.currentTime = this.audioNode.currentTime;
    });
    this.audioNode.addEventListener("ended", () => {
      !this.loop && (this.isPlay = false);
    });

    this.$nextTick(() => {
      document
        .querySelector(".audio-volume .el-tooltip.el-slider__button")
        .addEventListener("mousedown", () => {
          this.isPlay = false;
          this.isNoInput = true;
          this.audioNode.paused && (this.isCanPlay = true);
          this.audioPause();
        });

      this.audioContent.bgColor &&
        (document.querySelector(".el-dialog__body").style.background =
          this.audioContent.bgColor);

      this.audioPlay();
    });
  },
  computed: {
    formatTime() {
      return (time) => {
        let it = parseInt(time);
        let m = parseInt(it / 60);
        let s = parseInt(it % 60);
        return (
          (m < 10 ? "0" : "") +
          parseInt(it / 60) +
          ":" +
          (s < 10 ? "0" : "") +
          parseInt(it % 60)
        );
      };
    }
  },
  beforeDestroy() {
    this.audioNode && this.audioNode.load();
  },
  methods: {
    /**
     * 播放音乐
     */
    audioPlay() {
      this.isCanPlay = false;

      this.audioNode
        .play()
        .then(() => {
          // 音频加载成功
          this.isPlay = true;
        })
        .catch((e) => {
          this.$message.error("音频加载失败");
        });
    },
    /**
     * 暂停音乐
     */
    audioPause() {
      this.isPlay = false;
      this.audioNode.pause();
    },
    /**
     *
     */
    inputTime(time) {
      !this.isNoInput && this.audioNode.paused && (this.isCanPlay = true);
    },
    changeTime(time) {
      this.audioNode.currentTime = time;
      !this.isCanPlay && this.audioPlay();
      this.isCanPlay = false;
      this.isNoInput = false;
    },
    /**
     * 关闭音频弹窗
     */
    cancel() {
      this.onClose();
    }
  }
};
</script>

<style lang="scss">
.zh-audio-player {
  width: 80%;
  margin: auto;
  height: 200px;
  position: relative;
  line-height: normal;
  .no-support {
    display: flex;
    align-self: center;
    font-size: 18px;
    font-weight: 600;
    color: #1a1819;
  }
  .audio-viewer-index {
    position: absolute;
    top: -12px;
    left: 160px;
    width: 54px;
    transform-origin: 12px 12px;
    transition: all 1s;
    transform: rotate(8deg);
  }

  .audio-viewer-index-pause {
    transform: rotate(-26deg);
  }

  .audio-viewer-wrapper {
    display: flex;
    align-items: stretch;
    height: 100%;
    .audio-viewer-image {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 200px;
      height: 200px;
      border-radius: 50%;
      background: repeating-radial-gradient(
        ellipse farthest-corner,
        #1e1e1e,
        #222 5%,
        #222 5%,
        #222 10%
      );

      > div {
        display: flex;
        align-items: center;
        justify-content: center;
        background-image: linear-gradient(#4962d0, #528de7);
        height: 120px;
        width: 120px;
        border-radius: 50%;

        .audio-viewer-image-status {
          position: relative;
          width: 44px;
          height: 44px;
          box-sizing: border-box;
          border: 2px solid #fff;
          border-radius: 50%;

          &::before {
            left: 25px;
            top: 0;
            content: "";
            width: 2px;
            height: 21px;
            display: block;
            position: absolute;
            background: #fff;
          }

          &::after {
            content: "";
            width: 10px;
            height: 10px;
            display: block;
            border-radius: 50%;
            border: 2px solid #fff;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
          }
        }
      }
    }

    .audio-viewer-image-play {
      animation: pinwheel 3s linear infinite;
    }

    @keyframes pinwheel {
      0% {
        transform: rotate(0deg);
      }

      100% {
        transform: rotate(360deg);
      }
    }

    .audio-viewer-actions {
      display: flex;
      flex: 1;
      margin-left: 44px;
      height: 100%;
      .audio-action-status {
        display: flex;
        align-items: center;
        margin-right: 30px;
        flex-direction: column;
        justify-content: center;

        i {
          color: #000;
          font-size: 60px;
          cursor: pointer;
        }

        .audio-volume-sound {
          margin-top: 10px;

          .el-slider__runway {
            background: #fff;

            .el-tooltip.el-slider__button {
              border: none;
              width: 14px;
              height: 14px;
            }

            .el-slider__bar {
              background-image: linear-gradient(to right, #0077ff, #40b7ff);
            }
          }
        }
      }

      .audio-action-info {
        display: flex;
        flex: 1;
        justify-content: stretch;
        flex-direction: column;
        height: 100%;
        .audio-title {
          box-sizing: border-box;
          line-height: 80px;
          margin: 0;
          font-size: 20px;
          color: #000000;
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
          max-width: 380px;
          height: 40%;
        }

        .audio-volume {
          .audio-time {
            display: flex;
            justify-content: space-between;
            font-size: 16px;
            color: #000;
            height: 20px;
          }

          .el-slider {
            .el-slider__runway {
              background: #fff;

              .el-tooltip.el-slider__button {
                border: none;
                width: 18px;
                height: 18px;
              }

              .el-slider__bar {
                background-image: linear-gradient(to right, #0077ff, #40b7ff);
              }
            }
          }
        }
      }
    }
  }
}
</style>
